use crate::lexer::Token;

#[derive(Debug)]
pub enum ParseResult {
    Ok(Program),
    Err(Vec<String>),
}

/// 简化 AST 节点，只为 formatter 提供足够信息
#[derive(Debug, Clone)]
pub enum Node {
    CompUnit(Vec<Node>),
    ConstDecl { defs: Vec<String> }, // raw text segments for simplicity
    VarDecl { defs: Vec<String> },
    FuncDef { rettype: String, name: String, params: Vec<String>, body: Box<Node> },
    Block(Vec<Node>),
    Stmt(String), // keep raw text for simple printing
}

/// top-level program AST
#[derive(Debug, Clone)]
pub struct Program {
    pub items: Vec<Node>,
}

pub struct Parser {
    tokens: Vec<Token>,
    pos: usize,
    pub errors: Vec<String>,
}

impl Parser {
    pub fn new(tokens: Vec<Token>) -> Self {
        Parser {
            tokens,
            pos: 0,
            errors: Vec::new(),
        }
    }

    fn peek(&self) -> Option<&Token> {
        self.tokens.get(self.pos)
    }
    fn nth(&self, n: usize) -> Option<&Token> {
        self.tokens.get(self.pos + n)
    }
    fn bump(&mut self) -> Option<Token> {
        let t = self.tokens.get(self.pos).cloned();
        if t.is_some() {
            self.pos += 1;
        }
        t
    }
    fn expect(&mut self, kinds: &[&str]) -> Option<Token> {
        if let Some(t) = self.peek() {
            if kinds.iter().any(|k| k == &t.kind) {
                return self.bump();
            } else {
                // report unexpected
                self.errors.push(format!(
                    "Error type B at Line {}: mismatched input '{}' expecting {:?}",
                    t.line, t.text, kinds
                ));
                return None;
            }
        } else {
            // EOF
            self.errors.push(format!("Error type B at Line {}: unexpected EOF", self.last_line()));
            return None;
        }
    }

    fn last_line(&self) -> usize {
        if let Some(last) = self.tokens.last() {
            last.line
        } else {
            1
        }
    }

    // synchronization: skip tokens until one of sync tokens appear or EOF
    fn sync(&mut self) {
        let sync_kinds = ["SEMICOLON", "R_BRACE", "R_PAREN"];
        while let Some(t) = self.peek() {
            if sync_kinds.contains(&t.kind.as_str()) {
                // if semicolon or bracket is sync point, we will consume it and return
                self.bump();
                return;
            } else {
                self.bump();
            }
        }
    }

    // parse CompUnit -> (Decl | FuncDef)*
    pub fn parse_compunit(&mut self) -> ParseResult {
        let mut items = Vec::new();
        while self.peek().is_some() {
            // decide whether it's decl or funcdef
            // lookahead: expect 'const'|'int'|'void'
            let t = self.peek().unwrap().clone();
            if t.kind == "CONST" || t.kind == "INT" || t.kind == "VOID" {
                // further lookahead to see if a function: after type + IDENT + '(' => func
                if let Some(next1) = self.nth(1) {
                    if next1.kind == "IDENT" {
                        // look for '(' after that
                        if let Some(next2) = self.nth(2) {
                            if next2.kind == "L_PAREN" {
                                // function
                                match self.parse_funcdef() {
                                    Some(f) => items.push(f),
                                    None => { self.sync(); }
                                }
                                continue;
                            }
                        }
                    }
                }
                // otherwise it's a declaration
                match self.parse_decl() {
                    Some(d) => items.push(d),
                    None => { self.sync(); }
                }
            } else {
                // unexpected token at top-level
                self.errors.push(format!(
                    "Error type B at Line {}: unexpected token '{}'",
                    t.line, t.text
                ));
                self.bump();
            }
        }

        if self.errors.is_empty() {
            ParseResult::Ok(Program { items })
        } else {
            ParseResult::Err(self.errors.clone())
        }
    }

    // parse Decl -> ConstDecl | VarDecl
    fn parse_decl(&mut self) -> Option<Node> {
        if let Some(t) = self.peek() {
            if t.kind == "CONST" {
                // parse const decl: 'const' 'int' ConstDef (',' ConstDef)* ';'
                self.bump(); // const
                self.expect(&["INT"]);
                let mut defs = Vec::new();
                loop {
                    // consume identifier and optional brackets and = init
                    let mut raw = String::new();
                    if let Some(id) = self.expect(&["IDENT"]) {
                        raw.push_str(&id.text);
                        // if next is L_BRACKT, collect until R_BRACKT
                        while let Some(nxt) = self.peek() {
                            if nxt.kind == "L_BRACKT" {
                                raw.push('[');
                                self.bump();
                                // collect tokens until we hit R_BRACKT
                                while let Some(tok) = self.peek() {
                                    raw.push_str(&tok.text);
                                    if tok.kind == "R_BRACKT" {
                                        self.bump();
                                        break;
                                    } else {
                                        self.bump();
                                    }
                                }
                                raw.push(']');
                            } else {
                                break;
                            }
                        }
                        // expect '='
                        if let Some(eq) = self.expect(&["ASSIGN"]) {
                            raw.push_str(" = ");
                            // collect init simple - until comma or semicolon balanced braces
                            let mut depth = 0usize;
                            while let Some(tok) = self.peek() {
                                if tok.kind == "COMMA" && depth == 0 { break; }
                                if tok.kind == "SEMICOLON" && depth == 0 { break; }
                                if tok.kind == "L_BRACKT" || tok.kind == "L_BRACE" { depth += 1; }
                                if tok.kind == "R_BRACKT" || tok.kind == "R_BRACE" { if depth>0 { depth -= 1; } }
                                raw.push_str(&tok.text);
                                self.bump();
                            }
                        } else {
                            // error already added by expect
                            self.sync();
                        }
                    } else {
                        // error occurred
                        self.sync();
                        return None;
                    }

                    defs.push(raw);
                    // if comma, continue; if semicolon, break.
                    if let Some(nxt) = self.peek() {
                        if nxt.kind == "COMMA" {
                            self.bump();
                            continue;
                        } else if nxt.kind == "SEMICOLON" {
                            self.bump();
                            break;
                        } else {
                            // error
                            self.errors.push(format!(
                                "Error type B at Line {}: unexpected '{}' in declaration",
                                nxt.line, nxt.text
                            ));
                            self.sync();
                            break;
                        }
                    } else {
                        // EOF
                        self.errors.push(format!("Error type B at Line {}: unexpected EOF in declaration", self.last_line()));
                        break;
                    }
                }
                return Some(Node::ConstDecl { defs });
            } else if t.kind == "INT" {
                // VarDecl
                self.bump(); // int
                let mut defs = Vec::new();
                loop {
                    let mut raw = String::new();
                    if let Some(id) = self.expect(&["IDENT"]) {
                        raw.push_str(&id.text);
                        while let Some(nxt) = self.peek() {
                            if nxt.kind == "L_BRACKT" {
                                raw.push('[');
                                self.bump();
                                while let Some(tok) = self.peek() {
                                    raw.push_str(&tok.text);
                                    if tok.kind == "R_BRACKT" {
                                        self.bump();
                                        break;
                                    } else {
                                        self.bump();
                                    }
                                }
                                raw.push(']');
                            } else {
                                break;
                            }
                        }
                        // optional = init
                        if let Some(nxt) = self.peek() {
                            if nxt.kind == "ASSIGN" {
                                self.bump();
                                raw.push_str(" = ");
                                let mut depth = 0usize;
                                while let Some(tok) = self.peek() {
                                    if tok.kind == "COMMA" && depth == 0 { break; }
                                    if tok.kind == "SEMICOLON" && depth == 0 { break; }
                                    if tok.kind == "L_BRACKT" || tok.kind == "L_BRACE" { depth += 1; }
                                    if tok.kind == "R_BRACKT" || tok.kind == "R_BRACE" { if depth>0 { depth -= 1; } }
                                    raw.push_str(&tok.text);
                                    self.bump();
                                }
                            }
                        }
                    } else {
                        self.sync();
                        return None;
                    }

                    defs.push(raw);

                    if let Some(nxt) = self.peek() {
                        if nxt.kind == "COMMA" {
                            self.bump();
                            continue;
                        } else if nxt.kind == "SEMICOLON" {
                            self.bump();
                            break;
                        } else {
                            self.errors.push(format!(
                                "Error type B at Line {}: unexpected '{}' in var declaration",
                                nxt.line, nxt.text
                            ));
                            self.sync();
                            break;
                        }
                    } else {
                        self.errors.push(format!("Error type B at Line {}: unexpected EOF in var declaration", self.last_line()));
                        break;
                    }
                }
                return Some(Node::VarDecl { defs });
            }
        }
        None
    }

    // parse FuncDef -> FuncType Ident '(' [FuncFParams] ')' Block
    fn parse_funcdef(&mut self) -> Option<Node> {
        // rettype
        let rettype = if let Some(t) = self.bump() { t.text } else { return None; };
        // name
        let name = if let Some(id) = self.expect(&["IDENT"]) { id.text } else { self.sync(); return None; };
        // '('
        self.expect(&["L_PAREN"]);
        // collect params raw until ')'
        let mut params = Vec::new();
        // simple param collection: collect tokens between parentheses as text items split by commas
        let mut buf = String::new();
        let mut paren_depth = 1usize;
        while let Some(tok) = self.peek() {
            if tok.kind == "R_PAREN" && paren_depth == 1 {
                self.bump();
                if !buf.trim().is_empty() {
                    // split by comma
                    for p in buf.split(',') {
                        if !p.trim().is_empty() { params.push(p.trim().to_string()); }
                    }
                }
                break;
            } else {
                // record text
                if tok.kind == "L_PAREN" { paren_depth += 1; }
                if tok.kind == "R_PAREN" { if paren_depth>0 { paren_depth -= 1; } }
                buf.push_str(&tok.text);
                self.bump();
            }
        }
        // Block
        if let Some(block) = self.parse_block() {
            return Some(Node::FuncDef { rettype, name, params, body: Box::new(block) });
        } else {
            self.sync();
            return None;
        }
    }

    // parse Block -> '{' { BlockItem } '}'
    fn parse_block(&mut self) -> Option<Node> {
        if self.expect(&["L_BRACE"]).is_none() {
            self.sync();
            return None;
        }
        let mut items = Vec::new();
        while let Some(tok) = self.peek() {
            if tok.kind == "R_BRACE" {
                self.bump();
                break;
            }
            // BlockItem -> Decl | Stmt
            if tok.kind == "CONST" || tok.kind == "INT" {
                if let Some(d) = self.parse_decl() {
                    items.push(d);
                } else {
                    self.sync();
                }
            } else {
                // parse simple statement until semicolon or block or control stmt
                if let Some(s) = self.parse_stmt() {
                    items.push(s);
                } else {
                    self.sync();
                }
            }
        }
        Some(Node::Block(items))
    }

fn parse_stmt(&mut self) -> Option<Node> {
    if let Some(t) = self.peek().cloned() {
        match t.kind.as_str() {
            "L_BRACE" => return self.parse_block(),
            "IF" => {
                let mut buf = String::new();
                buf.push_str(&self.bump().unwrap().text); // consume IF
                let mut depth = 0usize;
                // 已修正：我们克隆了 peek 得到的 token，以避免借用冲突。
                while let Some(tok) = self.peek().cloned() {
                    buf.push_str(&tok.text);
                    if tok.kind == "L_BRACE" || tok.kind == "L_PAREN" {
                        depth += 1;
                    }
                    if tok.kind == "R_BRACE" || tok.kind == "R_PAREN" {
                        if depth > 0 {
                            depth -= 1;
                        }
                    }
                    if tok.kind == "ELSE" && depth == 0 {
                        break;
                    }
                    self.bump(); // 现在安全了
                    if tok.kind == "SEMICOLON" && depth == 0 {
                        break;
                    }
                }
                return Some(Node::Stmt(buf));
            }
            "WHILE" | "RETURN" | "BREAK" | "CONTINUE" => {
                let mut buf = String::new();
                // 已修正：我们克隆了 peek 得到的 token，以避免借用冲突。
                while let Some(tok) = self.peek().cloned() {
                    buf.push_str(&tok.text);
                    self.bump();
                    if tok.kind == "SEMICOLON" {
                        break;
                    }
                    if tok.kind == "L_BRACE" {
                        let mut depth = 1usize;
                        while let Some(t2) = self.bump() {
                            buf.push_str(&t2.text);
                            if t2.kind == "L_BRACE" {
                                depth += 1;
                            }
                            if t2.kind == "R_BRACE" {
                                depth -= 1;
                                if depth == 0 {
                                    break;
                                }
                            }
                        }
                        break;
                    }
                }
                return Some(Node::Stmt(buf));
            }
            _ => {
                let mut buf = String::new();
                while let Some(tok) = self.peek().cloned() {
                    buf.push_str(&tok.text);
                    self.bump();
                    if tok.kind == "SEMICOLON" {
                        break;
                    }
                }
                return Some(Node::Stmt(buf));
            }
        }
    }
    None
}
}